﻿using System;
using System.IO;
using System.Collections;
using System.Drawing;
using System.Windows.Forms;
using SharppiFlowEditor.models;
using SharppiFlowEditor.controllers;

namespace SharppiFlowEditor.views
{
    /*
 * The diagram editor window.
 */
    public class AppView : Form
    {
        // the diagram model
        private AppModel model;
        // the graphical view of the diagram
        public DocumentView document;
        public Panel panel;
        public Panel documentPanel;
        public Panel documentArea;
        public StatusBar sb;
        // the background of the diagramView, which shows only if the diagramView
        // is smaller than the space of the view, or the diagramView is not created
        public ScrollableControl diagramViewBackground;
        // the controllers: moving, creating nodes and connectors
        public DiagramController selC, nodeC, connC, delC, editC, saveC;
        public OpenDocumentController openC;
        public NewDocumentController newC;
        // the properties view of the selected diagramobject
        private NodePropertiesView nodePropertiesView;
        private ConnectorPropertiesView connPropertiesView;
        private DocumentPropertiesView docPropertiesView;

        public NodePropertiesView NodePropView { get { return nodePropertiesView; } }
        public ConnectorPropertiesView ConnPropView { get { return connPropertiesView; } }
        public DocumentPropertiesView DocPropView { get { return docPropertiesView; } } 

        // the main controller
        public AppController controller;
        // the status bar panel for instructions
        private StatusBarPanel modePanel;
        // a 'help' string
        private string note = "";

        // Application main menu
        private MainMenu appMainMenu = new MainMenu();
        private MenuItem fileMenu = new MenuItem("File");
        private MenuItem newDocumentMenuItem = new MenuItem("&New flowchart...");
        private MenuItem saveDocumentMenuItem = new MenuItem("&Save");
        private MenuItem saveAsDocumentMenuItem = new MenuItem("Save as...");
        private MenuItem exportDocumentImageMenuItem = new MenuItem("Export image (.jpg)");
        private MenuItem openDocumentMenuItem = new MenuItem("&Open...");
        private MenuItem printDocumentMenuItem = new MenuItem("&Print...");
        private MenuItem documentOverviewMenuItem = new MenuItem("Print over&view...");
        private MenuItem exitAppMenuItem = new MenuItem("&Exit");

        // Toolbar
        public DiagramToolBar diagramToolBar;

        // Kun nodella ja connectoreilla yhteinen ylaluokka, muuta Object ko. ylaluokaksi
        public Object ViewSelectedObject
        {
            set { document.SelectedObject = value; }
            get { return document.SelectedObject; }
        }

        // Create and initialize editor window
        public AppView(AppModel model)
        {
            // Model and controller
            this.model = model;
            controller = new AppController(this, model);

            Text = "Sharppi Flow Chart Editor";
            Size = new Size(1024, 740);
            Location = new Point(0, 0);

            // Create mainmenu
            CreateMenu();
            
            // Create toolbar
            diagramToolBar = new DiagramToolBar(this, controller);
            diagramToolBar.ZoomChanged += new DiagramToolBar.ZoomChangedEventHandler(diagramToolBar_ZoomChanged);
            Controls.Add(diagramToolBar.AppToolBar);

            // Create container for document and properties view
            panel = new Panel();
            panel.Dock = DockStyle.Fill;
            panel.Location = new Point(0, 0);
            panel.AutoSize = true;
            panel.Padding = new Padding(4, 50, 4, 0);

            // Create document and documentarea
            CreateDocumentArea();

            // Create properties pane for editing document size, nodes and connectors
            CreatePropertiesPane();
            
            // create the controllers
            nodeC = new CreateNodeController(this, model);
            connC = new CreateConnectorController(this, model);
            delC = new NodeDeleteController(this, model);
            editC = new EditPropertyController(this, model);
            openC = new OpenDocumentController(this, model);
            newC = new NewDocumentController(this, model);
            saveC = new SaveDocumentController(this, model);
            ((EditPropertyController)editC).GraphObjectSelected += new EditPropertyController.GraphSelectEventHandler(AppForm_GraphObjectSelected);
            this.KeyPreview = true;
            this.KeyDown += new KeyEventHandler(controller.ChangeController);

            // create a status bar
            sb = new StatusBar();
            modePanel = new StatusBarPanel();
            modePanel.Text = "Select/move elements mode" + note;
            modePanel.BorderStyle = StatusBarPanelBorderStyle.None;
            modePanel.AutoSize = StatusBarPanelAutoSize.Spring;
            sb.ShowPanels = true;
            sb.Panels.Add(modePanel);
            
            Controls.Add(panel);
            Controls.Add(sb);

            saveDocumentMenuItem.Enabled = false;
            saveAsDocumentMenuItem.Enabled = false;
            exportDocumentImageMenuItem.Enabled = false;
            printDocumentMenuItem.Enabled = false;
            documentOverviewMenuItem.Enabled = false;
        }

        private void CreateMenu()
        {
            // Application main menu
            appMainMenu = new MainMenu();
            fileMenu = new MenuItem("File");
            newDocumentMenuItem = new MenuItem("&New flowchart...");
            saveDocumentMenuItem = new MenuItem("&Save");
            saveAsDocumentMenuItem = new MenuItem("Save as...");
            exportDocumentImageMenuItem = new MenuItem("Export image (.jpg)");
            openDocumentMenuItem = new MenuItem("&Open...");
            printDocumentMenuItem = new MenuItem("&Print...");
            documentOverviewMenuItem = new MenuItem("Print over&view...");
            exitAppMenuItem = new MenuItem("&Exit");

            appMainMenu.MenuItems.Add(fileMenu);
            fileMenu.MenuItems.Add(newDocumentMenuItem);
            fileMenu.MenuItems.Add(openDocumentMenuItem);
            fileMenu.MenuItems.Add("-");
            fileMenu.MenuItems.Add(saveDocumentMenuItem);
            fileMenu.MenuItems.Add(saveAsDocumentMenuItem);
            fileMenu.MenuItems.Add(exportDocumentImageMenuItem);
            fileMenu.MenuItems.Add("-");
            fileMenu.MenuItems.Add(printDocumentMenuItem);
            fileMenu.MenuItems.Add(documentOverviewMenuItem);
            fileMenu.MenuItems.Add("-");
            fileMenu.MenuItems.Add(exitAppMenuItem);
            Menu = appMainMenu;

            newDocumentMenuItem.Click += new EventHandler(controller.NewDocument_Click);
            openDocumentMenuItem.Click += new EventHandler(controller.OpenDocument_Click);
            saveDocumentMenuItem.Click += new EventHandler(controller.SaveDocument_Click);
            saveAsDocumentMenuItem.Click += new EventHandler(controller.SaveAsDocument_Click);
            exportDocumentImageMenuItem.Click += new EventHandler(controller.ExportDocumentImage_Click);
            printDocumentMenuItem.Click += new EventHandler(controller.PrintDocument_Click);
            documentOverviewMenuItem.Click += new EventHandler(controller.DocumentOverview_Click);
            exitAppMenuItem.Click += new EventHandler(controller.ExitApp_Click);

            // Add shortcut keys for the menu items
            newDocumentMenuItem.Shortcut = Shortcut.CtrlN;
            openDocumentMenuItem.Shortcut = Shortcut.CtrlO;
            saveDocumentMenuItem.Shortcut = Shortcut.CtrlS;
            saveAsDocumentMenuItem.Shortcut = Shortcut.CtrlShiftS;
            exportDocumentImageMenuItem.Shortcut = Shortcut.CtrlE;
            printDocumentMenuItem.Shortcut = Shortcut.CtrlP;
            documentOverviewMenuItem.Shortcut = Shortcut.CtrlShiftP;
            exitAppMenuItem.Shortcut = Shortcut.CtrlQ;

        }

        private void CreateDocumentArea()
        {
            document = new DocumentView(model);
            document.Visible = false;
            document.Size = new System.Drawing.Size(500, 500);

            diagramViewBackground = new ScrollableControl();
            diagramViewBackground.BackColor = Color.LightGray;
            diagramViewBackground.Dock = DockStyle.Fill;
            diagramViewBackground.AutoScroll = true;

            documentPanel = new Panel();
            documentPanel.Dock = DockStyle.Fill;
            documentPanel.Location = new Point(0, 0);
            documentPanel.AutoSize = true;
            documentPanel.BorderStyle = BorderStyle.Fixed3D;

            documentArea = new Panel();
            documentArea.Dock = DockStyle.Fill;
            documentArea.BorderStyle = BorderStyle.Fixed3D;

            documentPanel.Controls.Add(diagramViewBackground);
            panel.Controls.Add(documentPanel);
            diagramViewBackground.Controls.Add(document);
        }

        private void CreatePropertiesPane()
        {
            Panel propertiesPane = new Panel();
            propertiesPane.Dock = DockStyle.Right;
            propertiesPane.Size = new Size(205, 650);
            propertiesPane.Padding = new Padding(2);

            GroupBox connPropertiesPane = new GroupBox();
            connPropertiesPane.Dock = DockStyle.Right;
            connPropertiesPane.Text = "Connector properties";
            connPropertiesPane.Dock = DockStyle.Top;
            connPropertiesPane.AutoSize = true;
            propertiesPane.Controls.Add(connPropertiesPane);

            GroupBox nodePropertiesPane = new GroupBox();
            nodePropertiesPane.Dock = DockStyle.Top;
            nodePropertiesPane.Text = "Node properties";
            nodePropertiesPane.AutoSize = true;
            nodePropertiesPane.Size = new System.Drawing.Size(200, 200);
            propertiesPane.Controls.Add(nodePropertiesPane);

            GroupBox docPropertiesPane = new GroupBox();
            docPropertiesPane.Dock = DockStyle.Right;
            docPropertiesPane.Text = "Document size";
            docPropertiesPane.Dock = DockStyle.Top;
            docPropertiesPane.AutoSize = true;
            docPropertiesPane.MinimumSize = new Size(0, 100);
            propertiesPane.Controls.Add(docPropertiesPane);

            nodePropertiesView = new NodePropertiesView();
            nodePropertiesView.Enabled = false;
            connPropertiesView = new ConnectorPropertiesView();
            connPropertiesView.Enabled = false;
            docPropertiesView = new DocumentPropertiesView();
            docPropertiesView.Enabled = false;

            docPropertiesView.Size = new System.Drawing.Size(200, 100);
            docPropertiesView.Dock = DockStyle.Top;

            nodePropertiesView.Size = new System.Drawing.Size(200, 200);
            nodePropertiesView.Dock = DockStyle.Top;
            nodePropertiesView.Location = new Point(0, 0);

            connPropertiesView.Size = new System.Drawing.Size(200, 150);
            connPropertiesView.Dock = DockStyle.Top;

            nodePropertiesPane.Controls.Add(nodePropertiesView);
            connPropertiesPane.Controls.Add(connPropertiesView);
            docPropertiesPane.Controls.Add(docPropertiesView);

            panel.Controls.Add(propertiesPane);
        }

        // Zoom functionality
        void diagramToolBar_ZoomChanged(object sender, EventArgs e)
        {
            String zoom = diagramToolBar.ZoomZomboBoxText;
            zoom = zoom.Remove(zoom.Length - 1);
            try
            {
                double zoomValue = Convert.ToInt32(zoom);
                zoomValue = zoomValue / 100;

                document.ZoomSize = zoomValue;
            }
            catch (Exception ex)
            {
            }
            
        }

        void AppForm_GraphObjectSelected(object sender, FlowChartEventArgs e)
        {
            if (e.ConnectorChanged != null)
            {
                connPropertiesView.SelectedGraphObject = e.ConnectorChanged;
                nodePropertiesView.clearPropertiesView();
                nodePropertiesView.Enabled = false;
                connPropertiesView.updatePropertiesView();
                connPropertiesView.Enabled = true;
            }
            else if (e.NodeChanged != null)
            {
                nodePropertiesView.SelectedGraphObject = e.NodeChanged;
                connPropertiesView.clearPropertiesView();
                connPropertiesView.Enabled = false;
                nodePropertiesView.updatePropertiesView();
                nodePropertiesView.Enabled = true;
            }
        }



        public void setDiagramVisible(bool visible)
        {
            saveDocumentMenuItem.Enabled = true;
            saveAsDocumentMenuItem.Enabled = true;
            exportDocumentImageMenuItem.Enabled = true;
            printDocumentMenuItem.Enabled = true;
            documentOverviewMenuItem.Enabled = true;
            document.Visible = visible;
            docPropertiesView.Enabled = true;
            diagramToolBar.SetEnabled(true);
        }

        public void changeHeadline(string mode)
        {
            this.Text = "Sharppi Flow Chart Editor - " + mode;
            modePanel.Text = mode + note;
        }

        private void InitializeComponent()
        {
            //base.OnSizeChanged(e);
            Size viewSize = this.Size;
            int width = viewSize.Width - (30 * 3);
            int height = viewSize.Height - (40 * 3);
            if (diagramViewBackground != null)
            {
                diagramViewBackground.Size = new Size((int)(width * 0.79), height);
            }
            if(nodePropertiesView != null)
            {
                nodePropertiesView.Size = new Size((int)(width * 0.18), nodePropertiesView.Size.Height);
            }
            if (connPropertiesView != null)
            {
                connPropertiesView.Size = new Size((int)(width * 0.18), connPropertiesView.Size.Height);
            }

            Invalidate();
            this.SuspendLayout();
            // 
            // AppView
            // 
            this.ClientSize = new System.Drawing.Size(284, 264);
            this.Name = "AppView";
            this.ResumeLayout(false);

        }


    }
}
